package org.txazo.music.web.filter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.txazo.music.util.md5.MD5;

/**
 * ETag过滤器
 * 
 * @author Tu XiaoZhou
 * @since 2013-04-13
 * 
 */
public class JspETagFilter implements Filter {

	public static final String ETAG_FLAG_BEGIN = "ETag/\"";
	public static final String ETAG_FLAG_END = "\"";
	public static final String ETAG = "ETag";
	public static final String IF_NONE_MATCH = "If-None-Match";
	public static final String LAST_MODIFIED = "Last-Modified";

	/** 静态资源后缀 */
	public static final String[] types = { "html", "css", "js", "jpg", "jpeg",
			"gif", "png", "ico" };

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;

		String uri = request.getServletPath();

		if (isStaticResource(uri)) {
			chain.doFilter(req, resp);
		} else if (uri.equals("/verifyCode")) {
			chain.doFilter(req, resp);
		} else {
			ByteArrayOutputStream buffer = new ByteArrayOutputStream();
			ETagResponseWrapper wrappedResponse = new ETagResponseWrapper(
					response, buffer);
			chain.doFilter(req, wrappedResponse);
			wrappedResponse.flushBuffer();

			byte[] bytes = buffer.toByteArray();

			String etag = ETAG_FLAG_BEGIN + MD5.md5(bytes) + ETAG_FLAG_END;
			String preETag = request.getHeader(IF_NONE_MATCH);

			response.setHeader(ETAG, etag);
			if (preETag != null && preETag.equals(etag)) {
				response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
			} else {
				response.setDateHeader(LAST_MODIFIED,
						System.currentTimeMillis());

				PrintWriter out = response.getWriter();
				out.write(new String(bytes));
				out.flush();
				out.close();
			}
		}
	}

	public static boolean isStaticResource(String uri) {
		String type = uri.substring(uri.lastIndexOf(".") + 1, uri.length());
		for (int i = 0; i < 8; i++) {
			if (type.equals(types[i])) {
				return true;
			}
		}
		return false;
	}

	@Override
	public void destroy() {
	}

}
